{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "0c3e96dc",
   "metadata": {},
   "source": [
    "# 站点间OD图绘制\n",
    "1. 计算各站点间OD量\n",
    "2. 划分为出行量大、中、小三类\n",
    "3. 获取线路站点数据\n",
    "4. 获取站点经纬度数据\n",
    "5. 使用pyecharts Geo绘制地图"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "498287f9",
   "metadata": {},
   "source": [
    "## 计算各站点间OD量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c16c6c1b",
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "\n",
    "import os\n",
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bd42e3a8",
   "metadata": {},
   "outputs": [],
   "source": [
    "data_path = 'D:\\\\todo\\\\4_智能运输信息处理技术_12_闭卷\\\\信息处理结课\\\\DataProcessed'\n",
    "files = os.listdir(data_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1db70976",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4月20日数据\n",
    "data = pd.read_csv(os.path.join(data_path, files[1]),encoding='gb18030',index_col=['trip'])\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ef917747",
   "metadata": {},
   "outputs": [],
   "source": [
    "data.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8bfaeaa8",
   "metadata": {},
   "outputs": [],
   "source": [
    "data.ori_discount.replace(['非优惠', '优惠'], [0, 1]).head()\n",
    "data.des_discount.replace(['非优惠', '优惠'], [0, 1]).head()\n",
    "data.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "abca5c84",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 获取所有站点\n",
    "stations = set.union(set(data.ori_station),set(data.des_station))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "30b18f95",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 站点经纬度数据\n",
    "location  = pd.read_csv(os.path.join(data_path, '经纬度.csv'))\n",
    "location.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "92f9ab1a",
   "metadata": {},
   "outputs": [],
   "source": [
    "Node = []\n",
    "for (station,i) in zip(stations,range(len(stations))):\n",
    "    if location.query('name == @station').shape[0] == 0:\n",
    "        x = 0\n",
    "        y = 0\n",
    "        print(station)\n",
    "    else:\n",
    "        \n",
    "        x = location.query('name == @station')['x'].iloc[0]\n",
    "        y = location.query('name == @station')['y'].iloc[0]\n",
    "    size = 5\n",
    "    color = '#5B9BD5'\n",
    "    n = {'name':station, 'x':x, 'y':y, 'color':color}\n",
    "    Node.append(n)\n",
    "\n",
    "Nodes = pd.DataFrame(Node, columns=['name', 'x', 'y', 'color'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7bc4d2c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "Edge = []\n",
    "# pd.DataFrame(columns = ['source', 'target', 'value'])\n",
    "for i in range(len(stations)):\n",
    "    for j in range(len(stations)):\n",
    "        if i != j :\n",
    "            source = Nodes.name.iloc[i]\n",
    "            target = Nodes.name.iloc[j]\n",
    "            value = data.query('ori_station == @source and des_station == @target').shape[0]\n",
    "            e = {'source':source, 'target':target, 'value':value}\n",
    "            Edge.append(e)\n",
    "#             e = pd.Series([source,target, value], index = Edge.columns)\n",
    "#             Edge.append(e, ignore_index=True)\n",
    "\n",
    "Edge"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc60005c",
   "metadata": {},
   "source": [
    "## 划分为出行量大、中、小三类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "059de520",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pyecharts import options as opts\n",
    "from pyecharts.charts import Geo\n",
    "from pyecharts.faker import Faker\n",
    "from pyecharts.globals import ThemeType, ChartType, SymbolType, CurrentConfig\n",
    "import  random\n",
    "\n",
    "nodes = pd.read_csv(os.path.join(data_path, 'Nodes.csv'), encoding = 'gb18030')\n",
    "links = pd.read_csv(os.path.join(data_path, 'Edges.csv'), encoding = 'gb18030')\n",
    "\n",
    "bounds = [0, 100, 300]\n",
    "s = links.query('value < 100')\n",
    "m = links.query('value > 100 & value < 300')\n",
    "l = links.query('value > 300')\n",
    "\n",
    "plotting_s = [(s.iloc[i]['source'], s.iloc[i]['target']) for i in range(len(s))]\n",
    "plotting_m = [(m.iloc[i]['source'], m.iloc[i]['target']) for i in range(len(m))]\n",
    "plotting_l = [(l.iloc[i]['source'], l.iloc[i]['target']) for i in range(len(l))]\n",
    "\n",
    "#自定义各地铁站的经纬度\n",
    "geo_cities_coords = {nodes.iloc[i]['name']:[nodes.iloc[i]['x'],nodes.iloc[i]['y']] for i in range(len(nodes))}\n",
    "\n",
    "#随机抽样20个地铁站组合\n",
    "# plotting_data = random.sample(list(plotting),20)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "30c74cf6",
   "metadata": {},
   "source": [
    "## 使用pyecharts Geo绘制地图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6c8a56ee",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pyecharts import Geolines, Style    #地理轨迹图的类就是Geolines\n",
    "\n",
    "#设置画布的格式\n",
    "style = Style(title_pos=\"center\", \n",
    "              width=1000, \n",
    "              height=800)\n",
    "\n",
    "#作图\n",
    "style_geolines = style.add(is_label_show=True,\n",
    "                      line_curve=0.3,             \n",
    "                      line_opacity=0.6,           \n",
    "                      geo_effect_symbol='none', \n",
    "                      geo_effect_symbolsize=10,   \n",
    "                      geo_effect_color='#7FFFD4',\n",
    "                      geo_effect_traillength=0.1,\n",
    "                      label_color=['#FFA500', '#FFF68F','#5B9BD5'],\n",
    "                      border_color='#97FFFF',  \n",
    "                      geo_normal_color='#36648B', \n",
    "                      label_formatter=\"{b}\", \n",
    "                      is_legend_show=True,\n",
    "                      legend_pos = 'left',\n",
    "                      legend_selectdmode = 'single')   #单例模式\n",
    "\n",
    "geolines = GeoLines('上海市地铁出行数据', **style.init_style)\n",
    "geolines.add('出行量小',          #图例1名称\n",
    "             plotting_s,\n",
    "             maptype='上海',    \n",
    "             geo_cities_coords=geo_cities_coords,\n",
    "             **style_geolines)\n",
    "geolines.add('出行量中等',            #图例2名称\n",
    "             plotting_m,\n",
    "             maptype='上海',  \n",
    "             geo_cities_coords=geo_cities_coords,\n",
    "             **style_geolines)\n",
    "geolines.add('出行量大',            #图例2名称\n",
    "             plotting_l,\n",
    "             maptype='上海',  \n",
    "             geo_cities_coords=geo_cities_coords,\n",
    "             **style_geolines)\n",
    "\n",
    "#发布，得到图形的html文件\n",
    "# geolines.render()   \n",
    "geolines.render_notebook()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69df6660",
   "metadata": {},
   "source": [
    "## 获取线路站点数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "83b540a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "from lxml import html\n",
    "from numpy import random\n",
    "\n",
    "import requests ##导入requests\n",
    "import xlwt\n",
    "\n",
    "headers =  {'User-Agent':'Mozilla/5.0'}\n",
    "user_agent_list = [\"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36\",\n",
    "                    \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36\",\n",
    "                    \"Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/61.0\",\n",
    "                    \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36\",\n",
    "                    \"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36\",\n",
    "                    \"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36\",\n",
    "                    \"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)\",\n",
    "                    \"Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15\",\n",
    "                    ]\n",
    "headers['User-Agent'] = random.choice(user_agent_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fc64ecf1",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import os\n",
    "import pdb\n",
    "pdb.set_trace()\n",
    "\n",
    "url = 'https://m.8684.cn/shanghai_dt_map'\n",
    "requests.adapters.DEFAULT_RETRIES = 5\n",
    "req = requests.get(url, headers=headers)\n",
    "#解析内容，获取所有的导航链接\n",
    "tree=html.etree.HTML(req.text)\n",
    "#查找线路集合\n",
    "lines_info = tree.xpath('//a[@class=\"cm-tt\"]/@href')\n",
    "\n",
    "all_info = []\n",
    "color = [      \"rgb(234,27,57)\", # 1号线\n",
    "      \"rgb(139,196,63)\", # 2号线\n",
    "      \"rgb(251,210,8)\", # 3号线 \n",
    "      \"rgb(81,45,141)\", # 4号线\n",
    "         \"rgb(81,45,141)\", # 4号线\n",
    "      \"rgb(144,86,163)\", # 5号线\n",
    "         \"rgb(144,86,163)\", # 5号线\n",
    "      \"rgb(214,24,112)\", #6号线\n",
    "      \"rgb(244,113,33)\", # 7号线\n",
    "      \"rgb(0,158,219)\", # 8号线\n",
    "      \"rgb(121,201,238)\", # 9号线\n",
    "      \"rgb(189,168,211)\", # 10号线\n",
    "         \"rgb(189,168,211)\", # 10号线\n",
    "      \"rgb(127,33,49)\", #11号线\n",
    "      \"rgb(1,124,103)\", # 12号线\n",
    "      \"rgb(232,149,193)\", # 13号线\n",
    "      \"rgb(94,92,41)\", # 14号线\n",
    "      \"rgb(187,167,134)\", # 15号线\n",
    "      \"rgb(142,209,192)\", # 16号线\n",
    "      \"rgb(184,121,116)\", # 17号线\n",
    "      \"rgb(186,160,81)\", # 18号线\n",
    "         \"rgb(255,255,255)\", # 21号线\n",
    "         \"rgb(255,255,255)\", # 磁悬浮\n",
    "         \"rgb(255,255,255)\", # 金山铁路\n",
    "         \"rgb(255,255,255)\" # 浦江线\n",
    "]\n",
    "\n",
    "data_path = 'D:\\\\todo\\\\4_智能运输信息处理技术_12_闭卷\\\\信息处理结课\\\\DataProcessed'\n",
    "nodes = pd.read_csv(os.path.join(data_path, '经纬度.csv'), encoding = 'gb18030')\n",
    "\n",
    "for line, c in zip(lines_info, color):\n",
    "    info = 'https://m.8684.cn'+line\n",
    "    print(info)\n",
    "    ls = requests.get(info, headers=headers)\n",
    "    lines_station= html.etree.HTML(ls.text)\n",
    "    \n",
    "    line_name = lines_station.xpath('//span[@class = \"line_txtl\"]/text()')\n",
    "    line_name = line_name[0].replace('上海地铁','')\n",
    "    print(line_name)\n",
    "    \n",
    "    stations = lines_station.xpath('//span[@bdlat]/text()')\n",
    "    print(stations)\n",
    "    \n",
    "    interrupt = len(stations)\n",
    "    for i in range(1, len(stations)):\n",
    "        if stations[i-1]==stations[i]:\n",
    "            interrupt = i\n",
    "            break\n",
    "    stations = stations[0:interrupt]\n",
    "    print(stations)\n",
    "    \n",
    "    process = []\n",
    "    for s in stations:\n",
    "        if len(nodes.query('station == @s'))==0:\n",
    "            process.append(s)\n",
    "    for s in process:\n",
    "        stations.remove(s)\n",
    "    \n",
    "#     draw_line = [(stations[i], stations[i+1]) for i in range(len(stations)-1)]\n",
    "    l = {'name':line_name, 'stations':stations, 'color':c}\n",
    "    all_info.append(l)\n",
    "# all_info = pd.DataFrame(all_info, columns=['name', 'stations', 'color'])\n",
    "# all_info.to_csv(os.path.join(data_path, 'lines_color.csv'), encoding = 'gb18030')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40741c78",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pdb\n",
    "pdb.set_trace()\n",
    "\n",
    "line_name = []\n",
    "pre_sta = []\n",
    "next_sta = []\n",
    "loc = []\n",
    "color = []\n",
    "for line in all_info:\n",
    "    stations = line['stations']\n",
    "    for i in range(len(stations)-1):\n",
    "        print(line['name'])\n",
    "        line_name.append(line['name'])\n",
    "        pre_sta.append(stations[i])\n",
    "        next_sta.append(stations[i+1])\n",
    "        pre_loc = location.query('station == @stations[@i]')\n",
    "        next_loc = location.query('station == @stations[@i+1]')\n",
    "        print(pre_loc)\n",
    "        print(next_loc)\n",
    "        loc.append('[%f,%f],[%f,%f]'%(pre_loc.x.iloc[0],pre_loc.y.iloc[0],next_loc.x.iloc[0],next_loc.y.iloc[0]))\n",
    "        color.append(line['color'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f11fbd35",
   "metadata": {},
   "outputs": [],
   "source": [
    "lines_Gaode = pd.DataFrame()\n",
    "lines_Gaode['line_name']=line_name\n",
    "lines_Gaode['pre_sta']=pre_sta\n",
    "lines_Gaode['next_sta']=next_sta\n",
    "lines_Gaode['loc']=loc\n",
    "lines_Gaode['color']=color\n",
    "lines_Gaode.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d7f1c8a3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 得到地铁线路数据\n",
    "lines_Gaode.to_csv(os.path.join(data_path,'lines_Gaode.csv'),  encoding = 'gb18030')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
